/**
 * A hibernate DAO class which supports simple CRUD operations on the account table.
 */
package com.booza.dao;

import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.booza.constants.AccountStatus;
import com.booza.constants.DatabaseConstants;
import com.booza.model.Account;

/**
 * A hibernate DAO class which supports simple CRUD operations on the account table. 
 * No business logic is coded in this class. Just the interaction with the database.
 * 
 * @see AccountDAO
 */
@Transactional
public class AccountDAOImpl implements AccountDAO
{
	@Autowired
	private SessionFactory sessionFactory;

	public SessionFactory getSessionFactory()
	{
		return sessionFactory;
	}

	public void setSessionFactory(SessionFactory sessionFactory)
	{
		this.sessionFactory = sessionFactory;
	}

	public void createAccount(Account account)
	{
		account.setCreatedate(new Date());
		Session session = sessionFactory.getCurrentSession();
		session.save(account);			
	}

	public Account findAccountById(Integer id)
	{
		return (Account) sessionFactory.getCurrentSession().get(DatabaseConstants.ACCOUNT_FQN, id);
	}

	public Account findAccountByEmail(String email)
	{
		return (Account) sessionFactory.getCurrentSession().createCriteria(Account.class).add(
				Restrictions.eq(DatabaseConstants.EMAIL_COLUMN, email)).uniqueResult();
	}

	public Account findAccountByUserId(String username)
	{
		return (Account) sessionFactory.getCurrentSession().createCriteria(Account.class).add(
				Restrictions.eq(DatabaseConstants.USERID_FQN, username)).uniqueResult();
	}

	public void updateAccount(Account account)
	{
		sessionFactory.getCurrentSession().update(account);
	}

	@SuppressWarnings("unchecked")
	public List<Account> fetchAccounts(Map<String, String> likeColumns)
	{
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Account.class);
		Set<String> keys = likeColumns.keySet();
		for (String s : keys) {
			criteria.add(Restrictions.like(s, likeColumns.get(s)).ignoreCase());
		}
		return (List<Account>) criteria.list();
	}

	@SuppressWarnings("unchecked")
	public List<Account> fetchAll()
	{
		return (List<Account>) sessionFactory.getCurrentSession().createCriteria(Account.class).list();
	}

	public Account checkConfirmationCode(String id)
	{
		return (Account) sessionFactory.getCurrentSession().createCriteria(Account.class).add(
				Restrictions.eq("confirmation", id)).uniqueResult();
	}

	@SuppressWarnings("unchecked")
	public Collection<Account> searchAccounts(String username)
	{
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Account.class);

		if (StringUtils.isEmpty(username) == false) criteria.add(Restrictions.like("userid", username + "%").ignoreCase());
		criteria.add(Restrictions.eq("status", AccountStatus.NORMAL));
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	public Collection<Account> getRankingsForDailyDeductions()
	{
		return (List<Account>) sessionFactory.getCurrentSession().createCriteria(Account.class).add(
				Restrictions.ge("ranking", 800.0)).list();
	}
}
